/*  File Name	: MessageBlock.cpp
 *  Author		: Pang Jiacai
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2012-4-25
 *  Description:
 */

#include "MessageBlock.h"
#include <stdlib.h>
#include "Logger.h"


MessageBlock::MessageBlock(int size)
{
	this->endian_ = this->endian();
	this->size_ = (size > 0) ? size : 512;
	this->left_size_ = this->size_;
	this->wr_len_ = 0;
	this->rd_ptr_ = NULL;
	this->wr_ptr_ = NULL;

	this->base_ptr_ = new char[sizeof(char)*size];//(char*)::malloc(sizeof(char)*size);
	if(NULL!=this->base_ptr_)
	{
		this->rd_ptr_ = this->base_ptr_;
		this->wr_ptr_ = this->base_ptr_;
		::memset(this->base_ptr_,'\0',size);
	}
}

MessageBlock::~MessageBlock()
{
	this->release();
}

void MessageBlock::release(void)
{
	if(NULL!=this->base_ptr_)
	{
		//::free((void*)this->base_ptr_);
		delete [] this->base_ptr_;
		this->base_ptr_ = NULL;
	}
	this->wr_ptr_ = NULL;
	this->rd_ptr_ = NULL;
}

void MessageBlock::destory(void)
{
	this->release();
	delete this;
}

void MessageBlock::reset(void)
{
	this->wr_len_ = 0;
	this->left_size_ = this->size_;
	this->rd_ptr_ = this->base_ptr_;
	this->wr_ptr_ = this->base_ptr_;
	::memset(this->base_ptr_,'\0',this->size_);
}

void MessageBlock::reset_rd_ptr(void)
{
	this->rd_ptr_ = this->base_ptr_;
}

void MessageBlock::reset_wr_ptr(void)
{
	this->wr_ptr_ = this->base_ptr_;
}

int MessageBlock::size(void) const
{
	return this->size_;
}

int MessageBlock::left_size(void) const
{
	return this->left_size_;
}

char *MessageBlock::base_ptr(void) const
{
	return this->base_ptr_;
}

char *MessageBlock::wr_ptr(void) const
{
	return this->wr_ptr_;
}

char *MessageBlock::rd_ptr(void) const
{
	return this->rd_ptr_;
}

void MessageBlock::rd_ptr(int n)
{
	if(this->rd_ptr_+n >=this->base_ptr_
			&& this->rd_ptr_+n <=this->base_ptr_+this->size_)
	{
		this->rd_ptr_ +=n;
	}
}

void MessageBlock::wr_ptr(int n)
{
	if(this->wr_ptr_+n >=this->base_ptr_
			&& this->wr_ptr_+n <=this->base_ptr_+this->size_)
	{
		this->wr_ptr_ +=n;
	}
}

void MessageBlock::wr_len(int len)
{
	this->wr_len_ += len;
}

int MessageBlock::data_len(void)
{
	return this->wr_len_;
}

int MessageBlock::left_rd_len(void)
{
	return (this->wr_ptr_-this->rd_ptr_);
}

int MessageBlock::write(const char *buf,int size)
{
	if(size <=0)
	{
		return 0;
	}
	if(NULL==buf || NULL==this->wr_ptr_
			|| this->left_size_ < size+1)
	{
		LOG((DEBUG_LOG,"MessageBlock::write error\n"));
		return -1;
	}

	::memcpy(this->wr_ptr_,buf,size);
	this->wr_ptr_ +=size;
	this->left_size_ -=size;
	this->wr_len_ +=size;
	return 0;
}

int MessageBlock::read(const char *buf,int size)
{
	if(NULL==buf|| size <=0 || NULL==this->rd_ptr_)
	{
		return -1;
	}
	if((this->rd_ptr_+size >this->base_ptr_+this->wr_len_))
	{
		return 0;
	}
	::memcpy((void*)buf,this->rd_ptr_,size);
	this->rd_ptr_ +=size;
	return 0;
}

MessageBlock & MessageBlock::operator <<(const int &i)
{
	int size = sizeof(int);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->wr_ptr_ || this->left_size_ < size + 1)
		{
			LOG((ERROR_LOG,"MessageBlock::operator <<(const int &i) error\n"));
			return *this;
		}

		char *p = (char*) &i;
		for (int i = 0; i < size; i++)
		{
			memcpy(this->wr_ptr_ + i * sizeof(char),
					(p + (size- 1 - i) * sizeof(char)), sizeof(char));
		}
		this->wr_ptr_ += size;
		this->left_size_ -= size;
		this->wr_len_ += size;
	}
	else
	{
		this->write((char*)&i,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator <<(const unsigned int &ui)
{
	int size = sizeof(unsigned int);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->wr_ptr_ || this->left_size_ < size + 1)
		{
			LOG((ERROR_LOG,"MessageBlock::operator <<(const unsigned int &ui) error\n"));
			return *this;
		}
		char *p = (char*) &ui;
		for (int i = 0; i < size; i++)
		{
			memcpy(this->wr_ptr_ + i * sizeof(char),
					(p + (size- 1 - i) * sizeof(char)), sizeof(char));
		}
		this->wr_ptr_ += size;
		this->left_size_ -= size;
		this->wr_len_ += size;
	}
	else
	{
		this->write((char*)&ui,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator <<(const short &s)
{
	int size = sizeof(short);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->wr_ptr_ || this->left_size_ < size + 1)
		{
			LOG((ERROR_LOG," MessageBlock::operator <<(const short &s) error\n"));
			return *this;
		}
		char *p = (char*) &s;
		for (int i = 0; i < size; i++)
		{
			memcpy(this->wr_ptr_ + i * sizeof(char),
					(p + (size- 1 - i) * sizeof(char)), sizeof(char));
		}
		this->wr_ptr_ += size;
		this->left_size_ -= size;
		this->wr_len_ += size;
	}
	else
	{
		this->write((char*)&s,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator <<(const float &f)
{
	int size = sizeof(float);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->wr_ptr_ || this->left_size_ < size + 1)
		{
			LOG((ERROR_LOG,"MessageBlock::operator <<(const float &f) error\n"));
			return *this;
		}
		char *p = (char*) &f;
		for (int i = 0; i < size; i++)
		{
			memcpy(this->wr_ptr_ + i * sizeof(char),
					(p + (size- 1 - i) * sizeof(char)), sizeof(char));
		}
		this->wr_ptr_ += size;
		this->left_size_ -= size;
		this->wr_len_ += size;
	}
	else
	{
		this->write((char*)&f,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator <<(const double &d)
{
	int size = sizeof(double);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->wr_ptr_ || this->left_size_ < size + 1)
		{
			LOG((ERROR_LOG,"MessageBlock::operator <<(const double &d) error\n"));
			return *this;
		}
		char *p = (char*) &d;
		for (int i = 0; i < size; i++)
		{
			memcpy(this->wr_ptr_ + i * sizeof(char),
					(p + (size- 1 - i) * sizeof(char)), sizeof(char));
		}
		this->wr_ptr_ += size;
		this->left_size_ -= size;
		this->wr_len_ += size;
	}
	else
	{
		this->write((char*)&d,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator <<(const long &l)
{
	int size = sizeof(long);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->wr_ptr_ || this->left_size_ < size + 1)
		{
			LOG((ERROR_LOG,"MessageBlock::operator <<(const long &l) error\n"));
			return *this;
		}
		char *p = (char*) &l;
		for (int i = 0; i < size; i++)
		{
			memcpy(this->wr_ptr_ + i * sizeof(char),
					(p + (size- 1 - i) * sizeof(char)), sizeof(char));
		}
		this->wr_ptr_ += size;
		this->left_size_ -= size;
		this->wr_len_ += size;
	}
	else
	{
		this->write((char*)&l,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator <<(const long long &ll)
{
	int size = sizeof(long long);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->wr_ptr_ || this->left_size_ < size + 1)
		{
			LOG((ERROR_LOG," MessageBlock::operator <<(const long long &ll) error\n"));
			return *this;
		}
		char *p = (char*) &ll;
		for (int i = 0; i < size; i++)
		{
			memcpy(this->wr_ptr_ + i * sizeof(char),
					(p + (size- 1 - i) * sizeof(char)), sizeof(char));
		}
		this->wr_ptr_ += size;
		this->left_size_ -= size;
		this->wr_len_ += size;
	}
	else
	{
		this->write((char*)&ll,size);
	}
	return *this;
}


MessageBlock & MessageBlock::operator <<(const std::string &str)
{

	short len = str.length();
	//this->write((char*) &len, sizeof(short));
	*this << len;
	this->write(str.c_str(), str.length());
	return *this;
}

MessageBlock & MessageBlock::operator <<(const char *buf)
{
	this->write(buf,strlen(buf));
	return *this;
}

MessageBlock & MessageBlock::operator <<(const char c)
{
	this->write(&c,sizeof(char));
	return *this;
}

MessageBlock & MessageBlock::operator >>(const int &i)
{
	int size = sizeof(int);
	if (this->endian_ == ENDIAN_BIG)
	{
		if(NULL==this->rd_ptr_ || (this->rd_ptr_+size >this->base_ptr_+this->wr_len_))
		{
			LOG((ERROR_LOG,"MessageBlock::operator >>(const int &i) error\n"));
			return *this;
		}
		char *p = (char*) &i;
		int char_size = sizeof(char);
		for (int i = 0; i < size; i++)
		{
			memcpy(p+i*char_size,this->rd_ptr_+(size-1-i)*char_size,char_size);
		}
		this->rd_ptr_ +=size;
	}
	else
	{
		this->read((char*)&i,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator >>(const unsigned int &ui)
{
	int size = sizeof(unsigned int);
	if (this->endian_ == ENDIAN_BIG)
	{
		if(NULL==this->rd_ptr_ || (this->rd_ptr_+size >this->base_ptr_+this->wr_len_))
		{
			LOG((ERROR_LOG,"MessageBlock::operator >>(const int &i) error\n"));
			return *this;
		}
		char *p = (char*) &ui;
		int char_size = sizeof(char);
		for (int i = 0; i < size; i++)
		{
			memcpy(p+i*char_size,this->rd_ptr_+(size-1-i)*char_size,char_size);
		}
		this->rd_ptr_ +=size;
	}
	else
	{
		this->read((char*)&ui,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator >>(const short &s)
{
	int size = sizeof(short);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->rd_ptr_ || (this->rd_ptr_ + size > this->base_ptr_ + this->wr_len_))
		{
			LOG((ERROR_LOG,"MessageBlock::operator >>(const int &i) error\n"));
			return *this;
		}
		char *p = (char*) &s;
		int char_size = sizeof(char);
		for (int i = 0; i < size; i++)
		{
			memcpy(p + i * char_size,
					this->rd_ptr_ + (size - 1 - i) * char_size, char_size);
		}
		this->rd_ptr_ += size;
	}
	else
	{
		this->read((char*) &s, size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator >>(const float &f)
{
	int size = sizeof(short);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->rd_ptr_ || (this->rd_ptr_ + size > this->base_ptr_ + this->wr_len_))
		{
			LOG((ERROR_LOG,"MessageBlock::operator >>(const float &f) error\n"));
			return *this;
		}
		char *p = (char*) &f;
		int char_size = sizeof(char);
		for (int i = 0; i < size; i++)
		{
			memcpy(p + i * char_size,
					this->rd_ptr_ + (size - 1 - i) * char_size, char_size);
		}
		this->rd_ptr_ += size;
	}
	else
	{
		this->read((char*)&f,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator >>(const double &d)
{
	int size = sizeof(double);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->rd_ptr_ || (this->rd_ptr_ + size > this->base_ptr_ + this->wr_len_))
		{
			LOG((ERROR_LOG,"MessageBlock::operator >>(const double &d) error\n"));
			return *this;
		}
		char *p = (char*) &d;
		int char_size = sizeof(char);
		for (int i = 0; i < size; i++)
		{
			memcpy(p + i * char_size,
					this->rd_ptr_ + (size - 1 - i) * char_size, char_size);
		}
		this->rd_ptr_ += size;
	}
	else
	{
		this->read((char*)&d,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator >>(const long &l)
{
	int size = sizeof(long);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->rd_ptr_ || (this->rd_ptr_ + size > this->base_ptr_ + this->wr_len_))
		{
			LOG((ERROR_LOG,"MessageBlock::operator >>(const long &l) error\n"));
			return *this;
		}
		char *p = (char*) &l;
		int char_size = sizeof(char);
		for (int i = 0; i < size; i++)
		{
			memcpy(p + i * char_size,
					this->rd_ptr_ + (size - 1 - i) * char_size, char_size);
		}
		this->rd_ptr_ += size;
	}
	else
	{
		this->read((char*)&l,size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator >>(const long long &ll)
{
	int size = sizeof(long long);
	if (this->endian_ == ENDIAN_BIG)
	{
		if (NULL == this->rd_ptr_
				|| (this->rd_ptr_ + size > this->base_ptr_ + this->wr_len_))
		{
			LOG((ERROR_LOG,"MessageBlock::operator >>(const long &l) error\n"));
			return *this;
		}
		char *p = (char*) &ll;
		int char_size = sizeof(char);
		for (int i = 0; i < size; i++)
		{
			memcpy(p + i * char_size,
					this->rd_ptr_ + (size - 1 - i) * char_size, char_size);
		}
		this->rd_ptr_ += size;
	}
	else
	{
		this->read((char*) &ll, size);
	}
	return *this;
}

MessageBlock & MessageBlock::operator >>( std::string &str)
{
	str.clear();
	short len = 0;
	*this >> len;
	if (len > 0)
	{
		str.resize(len);
		this->read((char*) str.c_str(), len);
	}
	return *this;
}

MessageBlock & MessageBlock::operator >>(const char &c)
{
	this->read(&c,sizeof(char));
	return *this;
}

int MessageBlock::endian(void)
{
	union
	{
		int testWord;
		char testByte[sizeof(int)];
	} endianTest;

	endianTest.testWord = 1;

	if (endianTest.testByte[0] == 1)
	{
		return ENDIAN_LITTLE;
	}
	return ENDIAN_BIG;
}

/*
 * write data len in the first sizeof(int) space
 */
int MessageBlock::write_len(void)
{
	if(this->size_<(int) sizeof(int))
	{
		return -1;
	}
	int len = this->data_len();
	::memcpy(this->base_ptr_,&len,sizeof(int));
	return 0;
}
